package com.adrian.misc.fractal;

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.adrian.misc.fractal.color.ExponentialColorMap;
import com.adrian.misc.fractal.color.SimpleColorMap;
import com.adrian.misc.fractal.color.TestColorMap;
import com.adrian.misc.fractal.color.TriColorColorMap;

public class FractalGUI implements ItemListener, ChangeListener, FractalListner, ActionListener, MouseListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 3162289782818545065L;
	public final static int GUI_APPLET = 1;
	public final static int GUI_STAND_ALONE = 2;
	public final static int GUI_JNLP = 3;
	
	JPanel vPanel = new JPanel (new GridLayout(8,1) );
	JPanel hPanel = new JPanel (new FlowLayout() );
	JButton zoomBtn = null;
	JButton resetBtn = null;
	JButton renderBtn = null;
	JLabel magLabel = new JLabel("1.0X");
	JLabel iterLabel = new JLabel("50");
	JCheckBox auto = new JCheckBox("Auto detail");
	JCheckBox adaptive = new JCheckBox("Auto Contrast");
	JCheckBox innerColor = new JCheckBox("Color Fractal set");
	JSlider itrBar = new JSlider(JSlider.HORIZONTAL,30,1000,100);
	FractalFrame popout;
	GraphicsDevice gd;
	private int guiType = 1;
	private Container cnt; 
	FractalCanvas fCan = new MandelbrotCanvas(400,400);
//	FractalCanvas mCan;
	ColorControl colCtrl;
	GUIService guiService;
	
	public FractalGUI(int GUIType, Container c) {
		cnt = c;
		guiType = GUIType;
		guiService = new GUIService(guiType, cnt);
		if ( (GUIType == GUI_APPLET) && !(c instanceof Applet) ){
			throw new IllegalArgumentException ("For GUI type GUI_APPLET container must be an applet");
		}
	}
	public void buildGUI() {
	/**   try {
		      UIManager.setLookAndFeel(new PlasticXPLookAndFeel ());
	   } catch (Exception e) {e.printStackTrace();} */

		cnt.setLayout(new BorderLayout());
		colCtrl = new ColorControl(fCan,155,600);
		//add(new JScrollPane((JComponent)fCan), BorderLayout.CENTER);
		cnt.add((JComponent)fCan, BorderLayout.CENTER);
        gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
		ImageIcon zoom = guiService.getIcon("zoom.gif");
		ImageIcon reset = guiService.getIcon("reset.png");
		ImageIcon render = guiService.getIcon("render.png");
		
		resetBtn = new JButton("Reset", reset);
		zoomBtn=new JButton("",zoom);
		renderBtn = new JButton("Render", render);
		
		zoomBtn.setActionCommand("zoom");
		//zoomBtn.setVerticalTextPosition(JButton.BOTTOM);
		zoomBtn.setHorizontalTextPosition(JButton.CENTER);
		zoomBtn.addActionListener(this);
		resetBtn.addActionListener(this);
		renderBtn.addActionListener(this);
		itrBar.addChangeListener(this);
		itrBar.addMouseListener(this);
		auto.addItemListener(this);	
		magLabel.setFont(new Font("Arial",Font.BOLD,14));
		magLabel.setSize(400,40);
		iterLabel.setFont(new Font("Arial",Font.BOLD,14));
		iterLabel.setSize(400,40);
		hPanel.add(magLabel);
		hPanel.add(auto);
		hPanel.add(itrBar);
		hPanel.add(iterLabel);
		itrBar.setSize(600,30);
		vPanel.add(zoomBtn);
		vPanel.add (resetBtn);
		vPanel.add (renderBtn);
		cnt.add(hPanel, BorderLayout.SOUTH);
		cnt.add(vPanel, BorderLayout.WEST);
		JPanel eastPanel = new JPanel();
		adaptive.setActionCommand("adaptive");
		innerColor.setActionCommand("inner");
		adaptive.addItemListener(this);
		innerColor.addItemListener(this);
		eastPanel.setLayout(new BoxLayout(eastPanel, BoxLayout.Y_AXIS));
		eastPanel.add(adaptive);
		eastPanel.add(innerColor);
		eastPanel.add(new JScrollPane(colCtrl,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
		cnt.add(eastPanel,BorderLayout.EAST);

		colCtrl.registerListner((ColorMapListner)fCan);
		fCan.registerFractalListner(this);
		colCtrl.add(new SimpleColorMap("Dark Orange..",Color.BLACK, Color.RED, Color.YELLOW,255));
//		colCtrl.add(new ExponentialColorMap("Radient Orange",Color.YELLOW, Color.YELLOW, Color.RED, 255));
		colCtrl.add(new ExponentialColorMap("Silver",Color.BLACK, Color.DARK_GRAY, Color.WHITE, 255));
		colCtrl.add(new TestColorMap("Deep Silver",Color.BLACK, Color.DARK_GRAY, Color.WHITE, 255));
		colCtrl.add(new TestColorMap("Deep golden",Color.BLACK, Color.BLACK, Color.YELLOW, 255));
		colCtrl.add(new TestColorMap("Gold Contours",Color.BLACK, Color.BLACK, Color.YELLOW,0.018,2.8,false, 255));
		colCtrl.add(new TestColorMap("Fringe gold",Color.BLACK, Color.BLACK, Color.YELLOW,0.003545,17.1,false, 255));
		colCtrl.add(new TestColorMap("Deep purple!!",Color.BLACK, Color.BLACK, new Color(180,80,255), 255));
		colCtrl.add(new TestColorMap("Purrrrple",Color.BLACK, Color.BLACK, new Color(180,80,255),0.018,2.8,false, 255));
		colCtrl.add(new TestColorMap("Fringe purple",Color.BLACK, Color.BLACK, new Color(180,80,255),0.003545,17.1,false, 255));
		colCtrl.add(new TriColorColorMap("Cool white",Color.BLACK, new Color(100,100,200), new Color(200,200,250),Color.BLACK,.3, 255));
		colCtrl.add(new TriColorColorMap("hmm..",Color.BLACK, Color.BLACK, Color.GRAY,new Color(180,180,255),.2, 255));
		colCtrl.add(new TestColorMap("Veins",Color.BLACK, Color.BLACK, new Color(255,25,25),0.018,2.8,false, 255));
		cnt.repaint();
	/**	colCtrl.add(new SimpleColorMap(Color.ORANGE, Color.BLACK, Color.RED,255));
		colCtrl.add(new SimpleColorMap(Color.BLACK, Color.BLACK, Color.BLUE,255));
		colCtrl.add(new SimpleColorMap(Color.ORANGE, new Color(50,50,255), Color.BLACK,255));
		colCtrl.add(new SimpleColorMap(Color.BLACK, Color.WHITE, Color.BLUE,255));
		colCtrl.add(new SimpleColorMap(Color.BLACK, Color.BLUE, Color.WHITE,255));
		colCtrl.add(new SimpleColorMap(Color.BLACK, Color.BLACK, Color.ORANGE,255));
		colCtrl.add(new SimpleColorMap(Color.PINK, Color.PINK, Color.BLACK,255));
		colCtrl.add(new SimpleColorMap(Color.BLACK, Color.CYAN, Color.DARK_GRAY,255));
		colCtrl.add(new SimpleColorMap(Color.BLACK, Color.MAGENTA, Color.BLACK,255));
		colCtrl.add(new SimpleColorMap(new Color(55,0,100), new Color(55,0,100), new Color(100,0,200),255));*/
	}

	public void itemStateChanged(ItemEvent e) {
		if (e.getSource() == adaptive) {
			if (e.getStateChange() == ItemEvent.SELECTED) {
				System.out.println("Adaptive");
				fCan.getFractal().setAdaptive(true);
			} else {
				System.out.println("Non-Adaptive");
				fCan.getFractal().setAdaptive(false);
			}
			fCan.setColorSync(false);
			fCan.repaint();
			return;
		}
		if (e.getSource() == innerColor) {
			if (e.getStateChange() == ItemEvent.SELECTED) {
				System.out.println("Inner coloring");
				fCan.getFractal().setInnerColor(true);
			} else {
				System.out.println("Plain coloring");
				fCan.getFractal().setInnerColor(false);
			}
			fCan.setColorSync(false);
			fCan.repaint();
			return;
			
		}
		if (e.getStateChange() == ItemEvent.SELECTED) {
			System.out.println( "Enabling");
			itrBar.setEnabled(false);
			fCan.getFractal().getFractalParam().iterations = -1;
			if (e.getSource() == auto ) {
				fCan.setSync(false);		
				fCan.setFromSelection();
			}
			return;
		}

		if (e.getSource() == auto ) {
			fCan.setSync(false);		
			fCan.setFromSelection();
		}
		fCan.getFractal().getFractalParam().iterations = itrBar.getValue();
		itrBar.setEnabled(true);
	}



	public void FractalChanged(Fractal f) {
		if (f.getFractalParam().iterations == -1){
			iterLabel.setText(""+ 22*(int)Math.pow( ((4.0/f.getFractalParam().fAreaMap.mathMap.width) * 100), .333) );
		}  else {
			iterLabel.setText(""+ f.getFractalParam().iterations);	
		}
		
		magLabel.setText("" + (int)(4.0/f.getFractalParam().fAreaMap.mathMap.width) + "X" );
	}

	public void stateChanged(ChangeEvent e) {
		fCan.getFractal().getFractalParam().iterations = ((JSlider)(e.getSource())).getValue();
		iterLabel.setText(""+fCan.getFractal().getFractalParam().iterations);		
	}

	public void actionPerformed(ActionEvent actn) {
		System.out.println("Command-"+actn.getActionCommand());
		if ( "zoom".equalsIgnoreCase( actn.getActionCommand() ) ) {
			System.out.println("Zoom");
			fCan.setSync(false);
			fCan.setFromSelection();
			fCan.repaint();
		}
		if ( "reset".equalsIgnoreCase( actn.getActionCommand() ) ) {
			System.out.println("reset");
			fCan.reset();
			fCan.setSync(false);			
			auto.setSelected(false);
			adaptive.setSelected(false);
			colCtrl.fireSelection();
			fCan.repaint();
		}

		if ( "render".equalsIgnoreCase( actn.getActionCommand() ) ) {
			System.out.println("Rendering");
			if (popout == null) {
				popout = new FractalFrame(fCan.getFractal());
			} else {
				popout.setFractal(fCan.getFractal());
			}
			popout.setVisible(true);
		}
		System.out.println("source - " + actn.getSource()); 
	}

	public void selectionChanged(FractalCanvas fc) {
		FractalParameters fp = fc.getFractal().getFractalParam();
		System.out.println("MAG Params-" + fc.getSelection().width+ ", "+ fp.fAreaMap.width +", " +fp.fAreaMap.mathMap.width);
		double mag = 4.0/ ( ((double) fc.getSelection().width /(double)fp.fAreaMap.width) * fp.fAreaMap.mathMap.width);
		zoomBtn.setText("<html><br><br>"+(int)mag+ "X</html>" );		
	}

	public void mouseClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void mouseReleased(MouseEvent me) {
		System.out.println("Mouse released!!");
		if (me.getSource() == itrBar ) {
			fCan.setSync(false);		
			fCan.setFromSelection();
			fCan.repaint();
		}
	}
}


